<template>
  <div :class="`tree-node level-${level}`">
    <span
      class="check-btn"
      :class="{
        checked: checkedStatus[model.adcode] === 'checked',
        indeterminate: checkedStatus[model.adcode] === 'indeterminate'
      }"
      @click="onCheckBtn"
    >
      <template v-if="checkedStatus[model.adcode] === 'checked'">✔</template>
      <template v-else-if="checkedStatus[model.adcode] === 'indeterminate'">-</template>
      <template v-else></template>
    </span>
    <span class="tree-label" @click="toggle">{{ model.name }}</span>
    <span
      class="tree-toggle"
      v-if="hasChildren"
      @click="toggle"
    >{{ expanded ? '▼' : '▶' }}</span>
    <div v-if="hasChildren && expanded" class="tree-children">
      <PreferRegionsTree
        v-for="child in children"
        :key="child.adcode"
        :model="child"
        :checkedStatus="checkedStatus"
        :expandedMap="expandedMap"
        :level="level + 1"
        @check="emitCheck"
      />
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import PreferRegionsTree from './PreferRegionsTree.vue'

const props = defineProps({
  model: Object,
  checkedStatus: Object,
  expandedMap: Object,
  level: { type: Number, default: 1 }
})
const emit = defineEmits(['check'])

const hasChildren = computed(() => props.model.cities || props.model.districts)
const children = computed(() => props.model.cities || props.model.districts)
const expanded = computed(() => props.expandedMap[props.model.adcode])

function toggle() {
  props.expandedMap[props.model.adcode] = !props.expandedMap[props.model.adcode]
}

function onCheckBtn() {
  const current = props.checkedStatus[props.model.adcode]
  emit('check', props.model, props.level, current !== 'checked')
}

function emitCheck(...args) {
  emit('check', ...args)
}

function initCheckedStatus(codes) {
  props.checkedStatus = {}

  // 全选
  if (!codes || codes.length === 0) {
    function setAll(node) {
      props.checkedStatus[node.adcode] = 'checked'
      if (node.cities) node.cities.forEach(setAll)
      if (node.districts) node.districts.forEach(setAll)
    }
    children.value.forEach(setAll)
    return
  }

  // 全不选
  if (codes.length === 1 && codes[0] === '-') {
    function clearAll(node) {
      props.checkedStatus[node.adcode] = ''
      if (node.cities) node.cities.forEach(clearAll)
      if (node.districts) node.districts.forEach(clearAll)
    }
    children.value.forEach(clearAll)
    return
  }

  // 正常递归
  function setAllChildrenChecked(node) {
    props.checkedStatus[node.adcode] = 'checked'
    if (node.cities) node.cities.forEach(child => setAllChildrenChecked(child))
    if (node.districts) node.districts.forEach(child => setAllChildrenChecked(child))
  }

  function walk(nodes) {
    nodes.forEach(node => {
      const adcode = node.adcode
      if (codes.includes(adcode)) {
        props.checkedStatus[adcode] = 'checked'
        if (node.cities) node.cities.forEach(child => setAllChildrenChecked(child))
        if (node.districts) node.districts.forEach(child => setAllChildrenChecked(child))
      } else {
        let childCodes = []
        if (node.cities) childCodes = node.cities.map(n => n.adcode)
        if (node.districts) childCodes = node.districts.map(n => n.adcode)
        if (childCodes.length) {
          walk(node.cities || node.districts)
          const allChecked = (node.cities || node.districts).every(child => props.checkedStatus[child.adcode] === 'checked')
          const someChecked = (node.cities || node.districts).some(child => props.checkedStatus[child.adcode] && props.checkedStatus[child.adcode] !== '')
          if (allChecked) {
            props.checkedStatus[adcode] = 'checked'
          } else if (someChecked) {
            props.checkedStatus[adcode] = 'indeterminate'
          } else {
            props.checkedStatus[adcode] = ''
          }
        } else {
          props.checkedStatus[adcode] = codes.includes(adcode) ? 'checked' : ''
        }
      }
    })
  }
  walk(children.value)
}

const collectCheckedCodes = () => {
  // 判断全选
  let allChecked = true
  function checkAll(nodes) {
    for (const node of nodes) {
      if (props.checkedStatus[node.adcode] !== 'checked') {
        allChecked = false
        break
      }
      const children = node.cities || node.districts
      if (children) checkAll(children)
    }
  }
  checkAll(children.value)
  if (allChecked) return []

  // 判断全不选
  let allEmpty = true
  function checkEmpty(nodes) {
    for (const node of nodes) {
      if (props.checkedStatus[node.adcode] === 'checked' || props.checkedStatus[node.adcode] === 'indeterminate') {
        allEmpty = false
        break
      }
      const children = node.cities || node.districts
      if (children) checkEmpty(children)
    }
  }
  checkEmpty(children.value)
  if (allEmpty) return ['-']

  // 正常收集
  const result = []
  function walk(nodes) {
    nodes.forEach(node => {
      const adcode = node.adcode
      if (props.checkedStatus[adcode] === 'checked') {
        result.push(adcode)
      } else if (props.checkedStatus[adcode] === 'indeterminate') {
        const children = node.cities || node.districts
        if (children) walk(children)
      }
    })
  }
  walk(children.value)
  return result
}
</script>

<style scoped>
.check-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: 2px solid #a259ff;
  border-radius: 5px;
  margin-right: 8px;
  font-size: 16px;
  cursor: pointer;
  background: #fff;
  color: #a259ff;
  transition: background 0.2s, color 0.2s;
}
.check-btn.checked {
  background: #a259ff;
  color: #fff;
  border-color: #a259ff;
}
.check-btn.indeterminate {
  background: #ffe0b2;
  color: #ff9800;
  border-color: #ff9800;
}
.check-btn:hover {
  box-shadow: 0 0 4px #a259ff55;
}
</style>
